package messagepasser;

/**
 * 
 * @author Rishit Shroff(rshroff)
 * @author Huimin Yang(huiminy)
 * @description Contains the description of the Logger class 
 */

import java.io.*;
import java.net.Socket;
import java.util.List;
import java.util.Timer;

import document.Document;

/**
 * 
 * Handle a received message, put it into the inputBuffer
 * 
 * @see ListenSocket
 *
 */
class ReceiveSocket extends Thread  {

	Message message;					// received Message
	List<Document> docs;
//	MessagePasser msgPasser;			// reference to MessagePasser Object
	ObjectInputStream inObjectStream;	// Input Object Stream
	Socket connection;					// Connection Socket

	/**
	 * Parameterized Constructor
	 * @param socket
	 * @param m			reference to the message Passer object
	 */
	ReceiveSocket ( Socket socket, List<Document> d)  {
		super ();
		connection =  socket;
		docs = d;
	}

	/**
	 *  Run method
	 */

	public void run  ()  {

		try  {
			inObjectStream = new ObjectInputStream (connection.getInputStream ());
			//debug
			// loop to read the incoming messages
			
			while ( true )  {

				message = (Message)inObjectStream.readObject();
				MessagePasser msgPasser = getPasser (message.getHeader().getId());
				synchronized (msgPasser) {
					//check for drop and delay types
					//Lab1
					TimeStampedMessage msg = (TimeStampedMessage)message;
					if (message.isMulticastMsg()) {

							// debug
						//	System.out.println("Socket recv multi, physical sender is " + msg.getPhySender());

							if(msg.getMsgType().contains("ack")) {
								//debug
								//			System.out.println("Got ack from " + msg.getHeader().getSrc());
								msgPasser.updateAckOfMsg(msg);
								return;
							}
							if(msg.getMsgType().equals("ok")) {
								//debug
								//System.out.println("Got ok from " + msg.getHeader().getSrc());
								msgPasser.moveToInputBuffer(msg);
								return;
							}
							else {
									msgPasser.addToReadyBuffer(message);
								//	msgPasser.networkToReady();
								}

								if (msgPasser.readyToReceive()) {
									for ( Message readyMessage : msgPasser.getReadyBuffer()) {
										msgPasser.acceptRealMessage((TimeStampedMessage)readyMessage);
									}
									msgPasser.emptyReadyBuffer();
								}
					}	 
					else {
						msgPasser.recvStamp((TimeStampedMessage)message);
						msgPasser.getInputBuffer().add(message);
					}
				}
				message = null;
			}  
		}
		catch ( Exception except ) {
			try  {
				connection.close ();
				return;
			}
			catch ( Exception e )  {
				e.printStackTrace ();
				return;
			}
		}
	}

	private MessagePasser getPasser(String id) {
		int Id = Integer.parseInt(id);
		
		for (Document d : docs) {
			if (d.docId == Id) {
				return d.myPasser;
			}
		}
		return null;
	}
}
